<!DOCTYPE html>
<!--
Copyright 2018 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->

<link rel="import" href="/tracing/metrics/metric_registry.html">

<script>
'use strict';

tr.exportTo('tr.metrics.tabs', function() {
  function tabsMetric(histograms, model, opt_options) {
    const chromeHelper = model.getOrCreateHelper(
        tr.model.helpers.ChromeModelHelper);
    if (!chromeHelper) {
      // Chrome isn't present.
      return;
    }

    const tabSwitchRequestDelays = [];
    const TAB_SWITCHING_REQUEST_TITLE = 'TabSwitchVisibilityRequest';
    // initialization, *startTabSwitchVisibilityRequest stores the
    // first legal TabSwitchVisibilityRequest's start time.
    let startTabSwitchVisibilityRequest = Number.MAX_SAFE_INTEGER;
    for (const helper of chromeHelper.browserHelpers) {
      if (!helper.mainThread) continue;
      for (const slice of helper.mainThread.asyncSliceGroup.slices) {
        if (slice.title === TAB_SWITCHING_REQUEST_TITLE && !slice.error) {
          tabSwitchRequestDelays.push(slice.duration);
          // find the first legal TabSwitchVisibilityRequest's start time
          if (slice.start < startTabSwitchVisibilityRequest) {
            startTabSwitchVisibilityRequest = slice.start;
          }
        }
      }
    }

    histograms.createHistogram('tab_switching_request_delay',
        tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
        tabSwitchRequestDelays, {
          description: 'Delay before tab-request is made',
          summaryOptions: {sum: false}});

    const tabSwitchLatencies = [];
    const TAB_SWITCHING_SLICE_TITLE = 'TabSwitching::Latency';

    function extractLatencyFromHelpers(helpers, legacy) {
      for (const helper of helpers) {
        if (!helper.mainThread) {
          continue;
        }
        const thread = helper.mainThread;
        for (const slice of thread.asyncSliceGroup.slices) {
          if (slice.title === TAB_SWITCHING_SLICE_TITLE &&
              (legacy || slice.args.latency) &&
              slice.start > startTabSwitchVisibilityRequest - 1 /* ms */) {
            // Push legal tabSwitchLatency which only starts after the
            // first legal TabSwitchVisibilityRequest's start time.
            // The tabSwitchLatency start time for a tab switch is earlier
            // than the corresponding TabSwitchVisibilityRequest start
            // time. Include tabSwitchLatency that is a little earlier
            // (within 1 ms) than startTabSwitchVisibilityRequest.
            tabSwitchLatencies.push(
                legacy ? slice.duration : slice.args.latency);
          }
        }
      }
    }

    extractLatencyFromHelpers(chromeHelper.browserHelpers);
    extractLatencyFromHelpers(Object.values(chromeHelper.rendererHelpers));

    if (tabSwitchLatencies.length === 0) {
      extractLatencyFromHelpers(chromeHelper.browserHelpers, true);
    }

    histograms.createHistogram('tab_switching_latency',
        tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
        tabSwitchLatencies, { description: 'Tab switching time in ms',
          summaryOptions: {sum: false}});
  }

  tr.metrics.MetricRegistry.register(tabsMetric, {
    supportsRangeOfInterest: false,
  });

  return {
    tabsMetric,
  };
});
</script>
